package com.alipay.service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.AlipayResponse;
import com.alipay.config.AlipayConfig;
import com.alipay.model.request.AlipayBaseRequest;
import com.alipay.model.response.AlipayBaseResponse;

/**
 * @author lwj
 * @create 2025-10-11-10:29
 *
 * 支付服务抽象类
 */
public abstract class AbstractPayService<Request extends AlipayBaseRequest, Response extends AlipayBaseResponse> {
    // 注入支付宝客户端和配置
    protected final AlipayClient alipayClient;
    protected final AlipayConfig alipayConfig;

    // 父类构造：子类需要传入客户端和配置
    public AbstractPayService(AlipayClient alipayClient, AlipayConfig alipayConfig) {
        this.alipayClient = alipayClient;
        this.alipayConfig = alipayConfig;
    }

    /**
     * 统一支付入口
     * @param request 请求参数
     * @return 响应参数
     */
    public Response pay(Request request){
        // 差异化支付宝请求对象
        AlipayRequest alipayRequest = createAlipayRequest();

        // 封装公共业务参数
        JSONObject bizContent = buildCommonBizContent(request);

        // 子类补充差异化参数
        fillBizContent(bizContent, request);

        // 子类根据请求类型设置请求参数（model/json型）
        setRequestParams(alipayRequest, bizContent);

        // 设置回调地址
        setCallbackUrl(alipayRequest);

        // 调用接口并处理响应
        try{
            AlipayResponse alipayResponse = executeAlipayRequest(alipayRequest);
            return handleAlipayResponse(alipayResponse, request);
        } catch (AlipayApiException e) {
            Response response = createEmptyResponse();
            response.setSuccess(false);
            response.setErrorMessage("支付请求失败：" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建支付宝请求对象，由子类来实现
     * @return 请求对象
     */
    protected abstract AlipayRequest createAlipayRequest();

    /**
     * 构建公共业务参数，子类可以进重新补充
     * @param request 请求参数
     * @return 业务参数
     */
    protected JSONObject buildCommonBizContent(Request request){
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", request.getOutTradeNo());
        bizContent.put("total_amount", request.getTotalAmount());
        bizContent.put("subject", request.getSubject());
        bizContent.put("body", request.getBody() != null ? request.getBody() : "");
        bizContent.put("timeout_express", request.getTimeout() != null ? request.getTimeout() : alipayConfig.getTimeout());
        bizContent.put("product_code", getProductCode());
        return bizContent;
    }

    /**
     * 填充差异化参数，由子类来实现
     * 例如：小程序添加 auth_token, 扫码支付添加 qr_code_timeout_express
     * @param bizContent 业务参数
     * @param request 请求参数
     */
    protected void fillBizContent(JSONObject bizContent, Request request){

    }

    /**
     * 设置请求参数，由子类来实现
     * @param alipayRequest 支付宝请求对象
     * @param bizContent 业务参数
     */
    protected abstract void setRequestParams(AlipayRequest alipayRequest, JSONObject bizContent);

    /**
     * 设置回调地址，子类可以进行重写补充
     * @param alipayRequest 支付宝请求对象
     */
    protected void setCallbackUrl(AlipayRequest alipayRequest){
        // 设置异步回调地址
        alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
    }

    /**
     * 执行支付宝请求，并返回响应结果
     * @param alipayRequest 支付宝请求对象
     * @return 支付宝响应结果
     */
    protected abstract AlipayResponse executeAlipayRequest(AlipayRequest alipayRequest)  throws AlipayApiException;

    /**
     * 处理支付宝响应结果，由子类来实现
     * @param alipayResponse 支付宝响应结果
     * @param request 请求参数
     * @return 响应参数
     */
    protected abstract Response handleAlipayResponse(AlipayResponse alipayResponse, Request request);

    /**
     * 创建空的响应结果，由子类来实现
     * @return 响应结果
     */
    protected abstract Response createEmptyResponse();

    /**
     * 获取产品码，由子类传递过来
     * @return 产品码
     */
    protected abstract String getProductCode();

    /**
     * 将支付宝响应结果填充到自定义响应对象中
     * @param response 自定义响应参数
     * @param alipayResponse 支付宝响应结果
     * @return 填充后的自定义响应参数
     */
    protected Response populateResponse(Response response,AlipayResponse alipayResponse){
        if(alipayResponse.isSuccess()){
            response.setSuccess(true);
            // 子类补充响应参数
            populateSpecificFields(response,alipayResponse);
        }else{
            response.setSuccess(false);
            response.setErrorCode(alipayResponse.getCode());
            response.setErrorMessage(alipayResponse.getMsg());
        }

        return response;
    }

    /**
     * 填充子类响应参数
     * @param response 响应参数
     * @param alipayResponse 支付宝响应结果
     */
    protected void populateSpecificFields(Response response, AlipayResponse alipayResponse){

    }
}